package my.chain;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.time.DateFormatUtils;

public class Test {

	private static Map<Integer, List<People>> commonPeopleMap = initPeopleList();

	private static List<People> smallBossList = initSmallBossList();

	private static List<People> bigBossList = initBigBossList();

	private static List<Integer> workDay = new ArrayList<Integer>();// 周末上班时间

	private static Map<Integer, Integer> holidayDateMap = new HashMap<Integer, Integer>();// 节假日

	private static int smallBossIndex = 0;

	private static int bigBossIndex = 0;

	private static int commonPeopleIndex = 0;

	static {
		holidayDateMap.put(20170101, 20170102);// 元旦
		holidayDateMap.put(20170127, 20170202);// 春节
		holidayDateMap.put(20170402, 20170404);// 清明节
		holidayDateMap.put(20170501, 20170501);// 劳动节
		holidayDateMap.put(20170528, 20170530);// 端午节
		holidayDateMap.put(20171001, 20171008);// 中秋节、国庆节

		// 周末要上班的时间
		workDay.add(20170122);
		workDay.add(20170204);
		workDay.add(20170401);
		workDay.add(20170527);
		workDay.add(20170930);
	}

	public static void main(String[] args) {

		Calendar c = Calendar.getInstance();

		// 值班人员排班
		Map<Integer, List<People>> rotaTableMap = createRotaTableOfCommonPeople();

		// 值班组长排班
		createRotaTableOfBoss(smallBossList);

		// 带班领导排班
		createRotaTableOfBoss(bigBossList);

		// 开始排班(排30天)
		for (int i = 0; i < 50; i++) {

			People smallBoss = getSmallBoss(c, smallBossList);

			People bigBoss = getBigBoss(c, bigBossList);

			List<People> peoples = getCommonPeopleList(rotaTableMap);

			// 值班人员
			System.out.println(DateFormatUtils.format(c.getTime(), "MM月dd日(E)") + "-->" + bigBoss + "," + smallBoss + "-->" + peoples);

			c.add(Calendar.DAY_OF_MONTH, 1);

		}
	}

	private static List<People> getCommonPeopleList(Map<Integer, List<People>> rotaTableMap) {
		if (commonPeopleIndex > rotaTableMap.size() - 1) {
			rotaTableMap = createRotaTableOfCommonPeople();
			commonPeopleIndex = 0;
		}
		List<People> peoples = rotaTableMap.get(commonPeopleIndex);
		reloadWorkCount(peoples);
		commonPeopleIndex++;
		return peoples;

	}

	private static People getBigBoss(Calendar c, List<People> bossList) {
		if (bigBossIndex > bossList.size() - 1) {
			bigBossIndex = 0;
		}
		
		if (bigBossIndex == 0) {
			createRotaTableOfBoss(bigBossList);
		}
		
		People people = getBoss(c, bigBossIndex, bossList);
		bigBossIndex++;
		return people;
	}

	private static People getSmallBoss(Calendar c, List<People> bossList) {
		if (smallBossIndex > bossList.size() - 1) {
			smallBossIndex = 0;
		}
		if(smallBossIndex == 0){
			createRotaTableOfBoss(bossList);			
		}
		
		People people = getBoss(c, smallBossIndex, bossList);
		smallBossIndex++;
		return people;
	}

	private static People getBoss(Calendar c, int index, List<People> bossList) {
		People boss = bossList.get(index);

		if (isHoliday(c.getTime()) || isWeekendDay(c.getTime())) {
			int workInHolidayCount = boss.getWorkInHolidayCount();
			if (workInHolidayCount != 0) {
				// 找一个节假日排班次数比我少的人,总的排版次数不会大于我
				People people = findBossWorkInHolidayLessThenMe(bossList, workInHolidayCount, boss.getWorkCount());
				if (people != null) {
					boss = people;
				}
			}
			boss.setWorkInHolidayCount(boss.getWorkInHolidayCount() + 1);
		}
		boss.setWorkCount(boss.getWorkCount() + 1);
		return boss;
	}

	/**
	 * 找一个节假日值班次数比他少的.(从当前的这个人的后面开始找)
	 * 
	 * @param smallBossList
	 * @param workInHolidayCount
	 * @return
	 */
	private static People findBossWorkInHolidayLessThenMe(List<People> smallBossList, int workInHolidayCount, int workCount) {

		/*for (int i = index + 1; i < smallBossList.size(); i++) {
			People people = smallBossList.get(i);
			if(people.getWorkInHolidayCount() < workInHolidayCount){
				return people;
			}
		}
		
		for (int i = 0; i < index; i++) {
			People people = smallBossList.get(i);
			if(people.getWorkInHolidayCount() < workInHolidayCount){
				return people;
			}
		}*/

		for (People people : smallBossList) {
			if (people.getWorkInHolidayCount() <= workInHolidayCount && people.getWorkCount() <= workCount) {
				return people;
			}
		}

		return null;
	}

	/**
	 * 创建排班表(领导或者组长)
	 * 
	 * @return
	 */
	private static void createRotaTableOfBoss(List<People> bossList) {
		sortNormalPeopleByWorkCount(bossList);
	}

	/**
	 * 创建排班表(普通值班人员)
	 * 
	 * @return
	 */
	private static Map<Integer, List<People>> createRotaTableOfCommonPeople() {

		List<People> newPeopleList = new ArrayList<People>();
		List<People> leftOverPeopleList = new ArrayList<People>();// 余下的人员

		for (Integer companyId : commonPeopleMap.keySet()) {
			List<People> peoples = commonPeopleMap.get(companyId);
			getLeftOverPeopleList(leftOverPeopleList, peoples, newPeopleList);
		}

		findSmallBossOf4People(newPeopleList, leftOverPeopleList);

		sortNormalPeopleByType(leftOverPeopleList);

		findSmallBossOf4People(leftOverPeopleList);

		// 分好组的人员加上剩下的人员
		newPeopleList.addAll(leftOverPeopleList);

		// 初步生成的排班表
		Map<Integer, List<People>> rotaMapList = listDataToManyListData(newPeopleList, 4);

		Integer lastKeyOfMap = rotaMapList.size() - 1;
		if ((rotaMapList.get(lastKeyOfMap).size()) % 4 != 0) {
			rotaMapList.remove(lastKeyOfMap);
		}

		// 校验阶段
		checkIshasSamllBossInEveryGroup(rotaMapList);
		// todo: 还需要校验节假日排班的次数

		//reloadWorkCount(rotaMapList);

		return rotaMapList;

	}

	/**
	 * 此时排班表就最终确定了,需要对排到的人员的次数进行计算
	 * 
	 * @param rotaMapList
	 */
	private static void reloadWorkCount(List<People> peoples) {
		//
		for (People people : peoples) {
			people.setWorkCount(people.getWorkCount() + 1);
		}
	}

	/**
	 * 验证每组里面的人是不是都包含一个科级干部
	 * 
	 * @param rotaMapList
	 */
	private static void checkIshasSamllBossInEveryGroup(Map<Integer, List<People>> rotaMapList) {
		//
		for (Iterator<Integer> iterator = rotaMapList.keySet().iterator(); iterator.hasNext();) {
			boolean isHasSamllBoss = false;
			Integer key = iterator.next();
			List<People> tempList = rotaMapList.get(key);
			for (People people : tempList) {
				if (people.getType() == 1) {
					isHasSamllBoss = true;
				}
			}
			if (!isHasSamllBoss) {
				iterator.remove();
			}
		}
	}

	/**
	 * 进行初步排班,得到剩下的一批人LeftOverPeopleList
	 * 
	 * @param LeftOverPeopleList
	 * @param peopleList
	 */
	private static void getLeftOverPeopleList(List<People> LeftOverPeopleList, List<People> peopleList, List<People> newPeopleList) {

		sortNormalPeopleByType(peopleList);

		findSmallBossOf4People(peopleList);

		Map<Integer, List<People>> peopleListMap = listDataToManyListData(peopleList, 4);

		for (Integer key : peopleListMap.keySet()) {
			List<People> temp = peopleListMap.get(key);
			if (temp.size() % 4 == 0) {
				newPeopleList.addAll(temp);
			} else {
				LeftOverPeopleList.addAll(temp);
			}
		}
	}

	/**
	 * 从剩下的人员列表中找一名科级干部
	 * 
	 * @param leftOverPeopleList
	 * @param newPeopleList
	 * @param index
	 */
	private static void findSmallBossIndexFromLeftOverPeopleList(List<People> leftOverPeopleList, List<People> newPeopleList, int index) {
		for (int i = 0; i < leftOverPeopleList.size(); i++) {
			People people = leftOverPeopleList.get(i);
			if (people.getType() == 1) {
				People newPeople = newPeopleList.get(index);
				newPeopleList.set(index, people);
				leftOverPeopleList.set(i, newPeople);
			}
		}
	}

	/**
	 * 将每个单位的人员按顺序排列(科级干部都往后面排)[普通人员,.....,科级干部,....]
	 * 
	 * @param peopleList
	 */
	private static void sortNormalPeopleByType(List<People> peopleList) {
		for (int i = 0; i < peopleList.size(); i++) {
			for (int j = 0; j < peopleList.size() - i - 1; j++) {
				if (peopleList.get(j).getType() == 1) {
					People people = peopleList.get(j);
					peopleList.set(j, peopleList.get(j + 1));
					peopleList.set(j + 1, people);
				}
			}
		}

		// 加入优先级的排序,优先排,排班次数少的人
		sortNormalPeopleByWorkCount(peopleList);
	}

	/**
	 * 将排到过的人按顺序往后面排(排到的次数越多,越靠后)
	 * 
	 * @param peopleList
	 */
	private static void sortNormalPeopleByWorkCount(List<People> peopleList) {
		for (int i = 0; i < peopleList.size(); i++) {
			for (int j = 0; j < peopleList.size() - i - 1; j++) {
				People people1 = peopleList.get(j);
				People people2 = peopleList.get(j + 1);
				if (people1.getWorkCount() > people2.getWorkCount()) {
					peopleList.set(j, people2);
					peopleList.set(j + 1, people1);
				}
			}
		}
	}

	private static void findSmallBossOf4People(List<People> peopleList) {
		findSmallBossOf4People(peopleList, null);
	}

	/**
	 * 每4个人中如果没有出现科级干部,就到后面的列表中寻找科级干部并替换第4个元素(基本上可以保证每4个人中肯定会包含一名科级干部,
	 * 除非后面的列表中没有科级干部)
	 * 
	 * 
	 * @param peopleList
	 * @param isFromLeftOverPeopleList
	 *            是否从剩下的人员列表中找
	 */
	private static void findSmallBossOf4People(List<People> peopleList, List<People> leftOverPeopleList) {
		int index = 1;
		boolean isHashSamllBoss = false;
		for (Iterator<People> iterator = peopleList.iterator(); iterator.hasNext();) {
			People people = iterator.next();

			if (people.getType() == 1) {
				isHashSamllBoss = true;
			}

			if (index % 4 == 0) {
				if (!isHashSamllBoss) {
					if (leftOverPeopleList != null) {
						findSmallBossIndexFromLeftOverPeopleList(leftOverPeopleList, peopleList, index - 1);
					} else {
						findSmallBossIndex(peopleList, index);
					}
				}
				isHashSamllBoss = false;
			}
			index++;
		}
	}

	/**
	 * 从startIndex开始寻找当前peopleList中符合条件的第一个对象,并替换(从后面找一名科级干部)
	 * 
	 * @param peopleList
	 * @param startIndex
	 */
	public static void findSmallBossIndex(List<People> peopleList, int startIndex) {
		for (int i = startIndex; i < peopleList.size(); i++) {
			People people = peopleList.get(i);
			if (people.getType() == 1) {
				People temp = peopleList.get(startIndex - 1);
				peopleList.set(startIndex - 1, people);
				peopleList.set(i, temp);
				break;
			}
		}
	}

	/**
	 * 将一个集合平均分成多份
	 * 
	 * @param data
	 * @param pageSize
	 * @return
	 */
	public static <T> Map<Integer, List<T>> listDataToManyListData(List<T> data, int pageSize) {
		int total = data.size();
		Map<Integer, List<T>> md = new LinkedHashMap<Integer, List<T>>();
		int count = total / pageSize;
		if (total % pageSize != 0) {
			count++;
		}
		for (int i = 0; i < count; i++) {
			List<T> list = new ArrayList<T>();
			for (int j = 1; j <= total; j++) {
				if (j > i * pageSize) {
					list.add(data.get(j - 1));
					if (j == (i + 1) * pageSize) {
						break;
					}
				}
			}
			md.put(i, list);
		}
		return md;
	}

	/**
	 * 判断某个日期是否是节假日
	 * 
	 * @param date
	 * @return
	 */
	private static boolean isHoliday(Date date) {
		int intDate = Integer.parseInt(DateFormatUtils.format(date, "yyyyMMdd"));

		for (Integer beginDate : holidayDateMap.keySet()) {
			if (intDate >= beginDate && intDate <= holidayDateMap.get(beginDate)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断是否是周末
	 * 
	 * @param date
	 * @return
	 */
	private static boolean isWeekendDay(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int weekIndex = c.get(Calendar.DAY_OF_WEEK) - 1;
		if (weekIndex == 6 || weekIndex == 0) {
			int intDate = Integer.parseInt(DateFormatUtils.format(date, "yyyyMMdd"));
			if (workDay.contains(intDate)) {
				return false;
			}
			return true;
		}
		return false;
	}

	private static List<People> initBigBossList() {
		List<People> bigBossList = new ArrayList<People>();
		bigBossList.add(new People("雄霸", 3, 1));
		bigBossList.add(new People("绝无神", 3, 1));
		bigBossList.add(new People("帝释天", 3, 1));
		bigBossList.add(new People("太阳神", 3, 1));
		bigBossList.add(new People("伏羲", 3, 1));
		bigBossList.add(new People("夸父", 3, 1));
		bigBossList.add(new People("刑天", 3, 1));
		bigBossList.add(new People("地魔兽", 3, 1));
		bigBossList.add(new People("老鬼", 3, 1));
		return bigBossList;

	}

	private static List<People> initSmallBossList() {
		List<People> smallBossList = new ArrayList<People>();
		smallBossList.add(new People("聂风", 2, 1000));
		smallBossList.add(new People("步惊云", 2, 1000));
		smallBossList.add(new People("秦霜", 2, 1000));
		smallBossList.add(new People("断浪", 2, 1000));
		smallBossList.add(new People("文丑丑", 2, 1000));
		smallBossList.add(new People("剑晨", 2, 1000));
		smallBossList.add(new People("第二梦", 2, 1000));
		return smallBossList;
	}

	private static Map<Integer, List<People>> initPeopleList() {
		Map<Integer, List<People>> companyPeopleMap = new LinkedHashMap<Integer, List<People>>();

		List<People> peopleList1001 = new ArrayList<People>();
		People p1 = new People("胡锦涛", 1, 1001);
		People p2 = new People("中国小弟1", 0, 1001);
		People p3 = new People("中国小弟2", 0, 1001);
		People p88 = new People("中国小弟3", 0, 1001);
		People p4 = new People("习近平", 1, 1001);
		People p0 = new People("温家宝", 1, 1001);

		peopleList1001.add(p1);
		peopleList1001.add(p2);
		peopleList1001.add(p3);
		peopleList1001.add(p4);
		peopleList1001.add(p0);
		peopleList1001.add(p88);

		List<People> peopleList1002 = new ArrayList<People>();
		People p5 = new People("美国小弟1", 0, 1002);
		People p6 = new People("美国小弟2", 0, 1002);
		People p7 = new People("美国小弟3", 0, 1002);
		People p8 = new People("美国小弟4", 0, 1002);
		People p9 = new People("奥巴马", 1, 1002);
		peopleList1002.add(p5);
		peopleList1002.add(p6);
		peopleList1002.add(p7);
		peopleList1002.add(p8);
		peopleList1002.add(p9);

		List<People> peopleList1003 = new ArrayList<People>();
		People p10 = new People("体育小弟1", 0, 1003);
		People p11 = new People("体育小弟2", 0, 1003);
		People p12 = new People("体育小弟3", 0, 1003);
		People p23 = new People("体育小弟4", 0, 1003);
		People p24 = new People("乔丹", 0, 1003);
		peopleList1003.add(p10);
		peopleList1003.add(p11);
		peopleList1003.add(p12);
		peopleList1003.add(p23);
		peopleList1003.add(p24);

		List<People> peopleList1004 = new ArrayList<People>();
		People p13 = new People("明星小弟1", 0, 1004);
		People p14 = new People("周杰伦", 1, 1004);
		People p15 = new People("蔡依林", 1, 1004);
		People p18 = new People("明星小弟2", 0, 1004);

		peopleList1004.add(p13);
		peopleList1004.add(p14);
		peopleList1004.add(p15);
		peopleList1004.add(p18);

		companyPeopleMap.put(1001, peopleList1001);
		companyPeopleMap.put(1002, peopleList1002);
		companyPeopleMap.put(1003, peopleList1003);
		companyPeopleMap.put(1004, peopleList1004);

		return companyPeopleMap;
	}

}
